package com.batchbrake.main;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import com.batchbrake.jobs.JobProc;
import com.batchbrake.queue.QueueEntity;

public class BatchBrakeProc extends Observable implements Runnable, Observer {
	public List<JobProc> procs = new ArrayList<JobProc>();
	public List<QueueEntity> queue = new ArrayList<QueueEntity>();
	private String preset = null;
	private boolean aborted = false;
	private boolean done = true;
	
	public BatchBrakeProc() {
		addProc(new JobProc("1st proc"));
//		addProc(new JobProc("2nd proc"));
	}
	
	public void addToQueue(QueueEntity e) {
		queue.add(e);
		this.setChanged();
		this.notifyObservers();
	}
	
	public void addToQueue(List<QueueEntity> e) {
		queue.addAll(e);
		this.setChanged();
		this.notifyObservers();
	}
	
	public void setQueue(List<QueueEntity> queue) {
		this.queue = queue;
		this.setChanged();
		this.notifyObservers();
	}
	
	public boolean removeFromQueue(QueueEntity e) {
		boolean success = queue.remove(e);
		this.setChanged();
		this.notifyObservers();
		return success;
	}
	
	public void addProc(JobProc proc) {
		procs.add(proc);
		proc.addObserver(this);
		this.setChanged();
		this.notifyObservers(proc);
	}
	
	public void stopAll() {
		for( int i = 0; i < procs.size(); i++ ) {
			procs.get(i).stop();
		}
		aborted = true;
	}
	
	public String getPreset() {
		return preset;
	}

	public void setPreset(String preset) {
		if( preset.equals("Normal") ) {
			this.preset = null;
		} else {
			this.preset = preset;
		}
	}

	public boolean isDone() {
		return done;
	}

	public void setDone(boolean done) {
		this.done = done;
	}

	@Override
	public void run() {
		boolean allTreated = false;
		aborted = false;
		done = false;
		this.setChanged();
		this.notifyObservers();
		
		while( !aborted && !allTreated ) {
			int procId = -1;
			while( !aborted && (procId == -1) ) {
				for( int i = 0; (procId == -1) && (i < procs.size()); i++ ) {
					if( !procs.get(i).isWorking() ) {
						procId = i;
					}
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			int entityId = -1;
			for( int i = 0; !aborted && (entityId == -1) && (i < queue.size()); i++ ) {
				if( !queue.get(i).isJobDone() && ((queue.get(i).getProc() == null) || !queue.get(i).getProc().isWorking()) ) {
					entityId = i;
				}
			}

			if( entityId == -1 ) {
				allTreated = true;
			} else {
				queue.get(entityId).setPreset(preset);
				queue.get(entityId).setProc(procs.get(procId));
				procs.get(procId).setJob(queue.get(entityId));
				new Thread(procs.get(procId)).start();
				this.setChanged();
				this.notifyObservers(procs.get(procId));

				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		done = true;
		this.setChanged();
		this.notifyObservers();
	}



	@Override
	public void update(Observable o, Object arg) {
		if( o instanceof JobProc ) {
			this.setChanged();
			this.notifyObservers(o);
		}
	}
}
